package com.pzcnet.core;

import com.pzcnet.model.*;
import com.pzcnet.service.EventBus;
import com.pzcnet.util.JSONUtil;
import com.rabbitmq.client.Channel;
import jdk.nashorn.internal.runtime.logging.Logger;
import lombok.extern.java.Log;
import lombok.extern.log4j.Log4j;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.ChannelAwareMessageListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class Receiver implements ChannelAwareMessageListener {

    @Autowired
    private EventBus eventBus;

    /**
     * 处理从MQ收到的消息
     *
     * @param message
     * @return true可以ACK，false不能ACK
     */
    public boolean receiveMessage(String message) {
        try {
            BaseEvent baseEvent = JSONUtil.parseJSON(message, BaseEvent.class);

            if (baseEvent.getEventType().equals(EventType.CALL_BACK.toString())) {
                EventCallBack eventCallBack = JSONUtil.parseJSON(message, EventCallBack.class);

                return this.eventBus.processCallBack(eventCallBack);
            } else {
                Event event = JSONUtil.parseJSON(message, Event.class);
                EventProcess eventProcess = new EventProcess(event);
                eventProcess.setId(null);
                eventProcess.setPublishId(event.getId());

                return this.eventBus.newProcess(eventProcess);
            }
        } catch (Exception e) {
            //TODO: 出现异常之后，是否ACK？
            log.error(e.getMessage(), e);
            return true;
        }
    }

    @Override
    public void onMessage(Message message, Channel channel) throws Exception {
        final long deliveryTag = message.getMessageProperties().getDeliveryTag();
        String messageBody = new String(message.getBody());

        log.info(String.format("Receive msg from MQ [%d]: %s", deliveryTag, messageBody));

        if (this.receiveMessage(messageBody)) {
            log.info(String.format("ACK msg [%d]: %s", deliveryTag, messageBody));
            channel.basicAck(deliveryTag, false);
        } else {
            log.info(String.format("N-ACK msg [%d]: %s", deliveryTag, messageBody));
            channel.basicNack(deliveryTag, false, true);
        }
    }
}
